﻿using CommunicationTools.Helper;
using Sunny.UI;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO.Ports;
using System.Linq;
using System.Net.Sockets;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading.Channels;

namespace CommunicationTools.Controls
{
    public partial class SocketDemo : UIPage
    {
        public SocketDemo()
        {
            InitializeComponent();
        }

        //判断是否打开
        private bool _isOpen = false;
        // 设置文件路径为当前目录下的LogFile.txt
        private string logFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "LogSocketFile.txt");
        //消息队列
        private Channel<string> _messageChannel;

        //Token
        CancellationTokenSource _ctsTCPClient = new CancellationTokenSource();
        CancellationTokenSource _ctsTCPServer = new CancellationTokenSource();
        CancellationTokenSource _ctsUDP = new CancellationTokenSource();

        bool _autoScroll = true;
        bool _ischeckRandom = false;
        private bool _log = false;

        Random rd = new Random();

        Encoding encode = Encoding.UTF8;

        //控制串口设置
        private void Enable(bool flag)
        {
            TCPClient_Radio.Enabled = flag;
            TcpServer_Radio.Enabled = flag;
            UDP_Radio.Enabled = flag;
            textbox_IP.Enabled = flag;
            //btn_random.Enabled = flag;
            if (TCPClient_Radio.Checked || UDP_Radio.Checked)
            {
                this.textbox_port.Enabled = true;
                this.textbox_localPort.Enabled = false;
            }
            if (TcpServer_Radio.Checked)
            {
                textbox_port.Enabled = false;
                textbox_localPort.Enabled = true;
            }
        }




        /// <summary>
        /// 连接
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void uiButton1_Click(object sender, EventArgs e)
        {
            try
            {
                if (_isOpen)
                {
                    //serialPort.Close();
                    btn_open.Text = "连接网络";
                    LogBox.AppendText("连接关闭".FormatStringLog());
                    Enable(true);
                    _ctsTCPClient?.Cancel();
                    _ctsTCPServer?.Cancel();
                    _ctsUDP?.Cancel();
                    //_cts?.Cancel();
                }
                else
                {
                    Enable(false);
                    btn_open.Text = "关闭连接";
                    //选择连接对象
                    if (TCPClient_Radio.Checked)
                    {
                        _ctsTCPClient = new CancellationTokenSource();
                        ConnectToTcpServer(textbox_IP.Text, textbox_port.Text.ToInt(), _ctsTCPClient.Token);
                    }
                    else if (TcpServer_Radio.Checked)
                    {
                        _ctsTCPServer = new CancellationTokenSource();
                        StartTcpServer(textbox_localPort.Text.ToInt(), _ctsTCPServer.Token);
                    }
                    else if (UDP_Radio.Checked)
                    {
                        _ctsTCPServer = new CancellationTokenSource();
                        StartUdpClient(textbox_IP.Text, textbox_port.Text.ToInt(), _ctsUDP.Token);
                    }




                }
            }
            catch (Exception ex)
            {
                // 处理异常
                Console.WriteLine("An error occurred: {0}", ex.Message);
            }
            finally
            {
                _isOpen = !_isOpen;
            }
        }




        //==============================连接网络===========================================

        // TcpClient方法
        public async Task ConnectToTcpServer(string ipAddress, int port, CancellationToken cts)
        {
            // 创建一个TcpClient实例
            using (TcpClient client = new TcpClient())
            {
                try
                {
                    // 解析IP地址
                    IPAddress ip = IPAddress.Parse(ipAddress);

                    // 创建一个远程端点
                    IPEndPoint remoteEndPoint = new IPEndPoint(ip, port);

                    // 连接到服务器
                    await client.ConnectAsync(remoteEndPoint);


                    LogBox.AppendText($"Connected to {ip}:{port}".FormatStringLog());
                    // 获取网络流
                    using (NetworkStream stream = client.GetStream())
                    {
                        // 初始化通道
                        _messageChannel = Channel.CreateUnbounded<string>(new UnboundedChannelOptions
                        {
                            SingleWriter = true,
                            SingleReader = true
                        });

                        // 开始监听通道中的数据并发送
                        Task senderTask = Task.Run(async () =>
                        {
                            await foreach (var message in _messageChannel.Reader.ReadAllAsync(cts))
                            {
                                await Task.Delay(100);
                                byte[] data = Encoding.ASCII.GetBytes(message);
                                await stream.WriteAsync(data, cts);

                                if (radio_send_ascii.Checked)
                                {
                                    Invoke(() =>
                                    {
                                        LogBox.AppendText($"Sent message:{message}".FormatStringLog());
                                        if (_autoScroll)
                                        {
                                            LogBox.SelectionStart = LogBox.Text.Length;
                                            LogBox.ScrollToCaret();
                                        }
                                    });
                                }
                                else
                                {
                                    Invoke(() =>
                                    {
                                        LogBox.AppendText($"Sent message:{message.StringToHexString(encode)}".FormatStringLog());
                                        if (_autoScroll)
                                        {
                                            LogBox.SelectionStart = LogBox.Text.Length;
                                            LogBox.ScrollToCaret();
                                        }
                                    });
                                }




                            }
                        }, cts);
                        // 开始接收来自服务器的消息
                        Task receiverTask = Task.Run(async () =>
                        {
                            byte[] buffer = new byte[1024];
                            while (!cts.IsCancellationRequested)
                            {
                                await Task.Delay(100);
                                int bytesRead = await stream.ReadAsync(buffer, cts);
                                string receivedMessage;

                                if (radio_save_ascii.Checked)
                                {
                                    receivedMessage = Encoding.ASCII.GetString(buffer, 0, bytesRead);
                                    Invoke(() =>
                                    {
                                        LogBox.AppendText($"Received message: {receivedMessage}".FormatStringLog());
                                        if (_autoScroll)
                                        {
                                            LogBox.SelectionStart = LogBox.Text.Length;
                                            LogBox.ScrollToCaret();
                                        }
                                    });
                                }
                                else if (radio_save_hex.Checked)
                                {
                                    receivedMessage = Encoding.ASCII.GetString(buffer, 0, bytesRead);
                                    Invoke(() =>
                                    {
                                        LogBox.AppendText($"Received message: {receivedMessage.StringToHexString(encode)}".FormatStringLog());
                                        if (_autoScroll)
                                        {
                                            LogBox.SelectionStart = LogBox.Text.Length;
                                            LogBox.ScrollToCaret();
                                        }
                                    });
                                }
                                else
                                {
                                    receivedMessage = Encoding.UTF8.GetString(buffer, 0, bytesRead);
                                    Invoke(() =>
                                    {
                                        LogBox.AppendText($"Received message: {receivedMessage}".FormatStringLog());
                                        if (_autoScroll)
                                        {
                                            LogBox.SelectionStart = LogBox.Text.Length;
                                            LogBox.ScrollToCaret();
                                        }
                                    });
                                }





                            }
                        }, cts);
                        // 等待发送和接收任务完成
                        await Task.WhenAny(senderTask, receiverTask, Task.Delay(-1, cts));
                    }
                }
                catch (SocketException e)
                {
                    MessageBox.Show("连接出错");
                }
                catch (Exception e)
                {
                    throw e;
                }
            }
        }


        //TCPServer方法
        public async Task StartTcpServer(int port, CancellationToken cts)
        {
            try
            {
                // 创建一个新的TcpListener实例来监听连接
                IPHostEntry host = Dns.GetHostEntry(Dns.GetHostName());
                //注意这里
                IPAddress ip = host.AddressList.FirstOrDefault(a => a.AddressFamily == AddressFamily.InterNetwork);
                IPEndPoint localEndPoint = new IPEndPoint(ip, port);
                using (TcpListener server = new TcpListener(localEndPoint))
                {


                    server.Start();

                    LogBox.AppendText($"Server started on {ip}:{port}".FormatStringLog());

                    while (!cts.IsCancellationRequested)
                    {
                        // 等待客户端连接
                        TcpClient client = await server.AcceptTcpClientAsync();
                        LogBox.AppendText($"Client connected from {((IPEndPoint)client.Client.RemoteEndPoint).Address}:{((IPEndPoint)client.Client.RemoteEndPoint).Port}".FormatStringLog());

                        // 获取网络流
                        using (NetworkStream stream = client.GetStream())
                        {
                            // 初始化通道
                            _messageChannel = Channel.CreateUnbounded<string>(new UnboundedChannelOptions
                            {
                                SingleWriter = true,
                                SingleReader = true
                            });

                            // 开始接收来自客户端的消息
                            Task receiverTask = Task.Run(async () =>
                            {
                                byte[] buffer = new byte[1024];
                                while (!cts.IsCancellationRequested)
                                {
                                    await Task.Delay(100);
                                    int bytesRead = await stream.ReadAsync(buffer, cts);
                                    string receivedMessage;
                                    if (radio_save_ascii.Checked)
                                    {
                                        receivedMessage = Encoding.ASCII.GetString(buffer, 0, bytesRead);
                                        Invoke(() =>
                                        {
                                            LogBox.AppendText($"Received message: {receivedMessage}".FormatStringLog());
                                            if (_autoScroll)
                                            {
                                                LogBox.SelectionStart = LogBox.Text.Length;
                                                LogBox.ScrollToCaret();
                                            }
                                        });
                                    }
                                    else if (radio_save_hex.Checked)
                                    {
                                        receivedMessage = Encoding.ASCII.GetString(buffer, 0, bytesRead);
                                        Invoke(() =>
                                        {
                                            LogBox.AppendText($"Received message: {receivedMessage.StringToHexString(encode)}".FormatStringLog());
                                            if (_autoScroll)
                                            {
                                                LogBox.SelectionStart = LogBox.Text.Length;
                                                LogBox.ScrollToCaret();
                                            }
                                        });
                                    }
                                    else
                                    {
                                        receivedMessage = Encoding.UTF8.GetString(buffer, 0, bytesRead);
                                        Invoke(() =>
                                        {
                                            LogBox.AppendText($"Received message: {receivedMessage}".FormatStringLog());
                                            if (_autoScroll)
                                            {
                                                LogBox.SelectionStart = LogBox.Text.Length;
                                                LogBox.ScrollToCaret();
                                            }
                                        });
                                    }

                                }
                            }, cts);

                            // 开始监听通道中的数据并发送到客户端
                            Task senderTask = Task.Run(async () =>
                            {
                                await foreach (var message in _messageChannel.Reader.ReadAllAsync(cts))
                                {
                                    await Task.Delay(100);
                                    byte[] data = Encoding.ASCII.GetBytes(message);
                                    await stream.WriteAsync(data, cts);

                                    if (radio_send_ascii.Checked)
                                    {
                                        Invoke(() =>
                                        {
                                            LogBox.AppendText($"Sent message: {message}".FormatStringLog());
                                            if (_autoScroll)
                                            {
                                                LogBox.SelectionStart = LogBox.Text.Length;
                                                LogBox.ScrollToCaret();
                                            }
                                        });
                                    }
                                    else
                                    {
                                        Invoke(() =>
                                        {
                                            LogBox.AppendText($"Sent message: {message.StringToHexString(encode)}".FormatStringLog());
                                            if (_autoScroll)
                                            {
                                                LogBox.SelectionStart = LogBox.Text.Length;
                                                LogBox.ScrollToCaret();
                                            }
                                        });
                                    }



                                }
                            }, cts);

                            // 等待发送和接收任务完成
                            await Task.WhenAny(senderTask, receiverTask, Task.Delay(-1, cts));
                        }

                        // 关闭连接
                        client.Close();
                    }
                }
            }
            catch (SocketException e)
            {
                MessageBox.Show("Server socket error" + e.Message);
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message);
            }
        }

        //UDP方法
        public async Task StartUdpClient(string ipAddress, int port, CancellationToken cts)
        {
            try
            {
                // 创建一个新的 UdpClient 实例
                using (UdpClient client = new UdpClient())
                {
                    // 设置远程端点
                    IPEndPoint remoteEndPoint = new IPEndPoint(IPAddress.Parse(ipAddress), port);

                    // 初始化通道
                    _messageChannel = Channel.CreateUnbounded<string>(new UnboundedChannelOptions
                    {
                        SingleWriter = true,
                        SingleReader = true
                    });

                    // 开始监听通道中的数据并发送
                    Task senderTask = Task.Run(async () =>
                    {
                        await foreach (var message in _messageChannel.Reader.ReadAllAsync(cts))
                        {
                            byte[] data = Encoding.ASCII.GetBytes(message);
                            await client.SendAsync(data, data.Length, remoteEndPoint);

                            Invoke(() =>
                            {
                                LogBox.AppendText($"Sent message: {message} to {ipAddress}:{port}".FormatStringLog());
                                if (_autoScroll)
                                {
                                    LogBox.SelectionStart = LogBox.Text.Length;
                                    LogBox.ScrollToCaret();
                                }
                            });
                        }
                    }, cts);

                    // 接收响应
                    Task receiverTask = Task.Run(async () =>
                    {
                        while (!cts.IsCancellationRequested)
                        {
                            UdpReceiveResult result = await client.ReceiveAsync(cts);
                            string receivedMessage = Encoding.ASCII.GetString(result.Buffer, 0, result.Buffer.Length);

                            Invoke(() =>
                            {
                                LogBox.AppendText($"Received response: {receivedMessage} from {result.RemoteEndPoint}".FormatStringLog());
                                if (_autoScroll)
                                {
                                    LogBox.SelectionStart = LogBox.Text.Length;
                                    LogBox.ScrollToCaret();
                                }
                            });
                        }
                    }, cts);

                    // 等待发送和接收任务完成
                    await Task.WhenAny(senderTask, receiverTask, Task.Delay(-1, cts));
                }
            }
            catch (SocketException e)
            {
                MessageBox.Show("UDP Socket error occurred.");
            }

        }










        //选择了TCPClient
        private void TCPClient_Radio_CheckedChanged(object sender, EventArgs e)
        {
            if (TCPClient_Radio.Checked)
            {
                this.textbox_port.Enabled = true;
                this.textbox_localPort.Enabled = false;
            }


        }
        //选择了TCPClient
        private void TcpServer_Radio_CheckedChanged(object sender, EventArgs e)
        {
            if (TcpServer_Radio.Checked)
            {
                textbox_port.Enabled = false;
                textbox_localPort.Enabled = true;
            }
        }


        //选择了UDP
        private void UDP_Radio_CheckedChanged(object sender, EventArgs e)
        {
            if (UDP_Radio.Checked)
            {
                textbox_port.Enabled = true;
                textbox_localPort.Enabled = false;
            }
        }


        //发送数据
        private void btn_send_Click(object sender, EventArgs e)
        {
            string message = textbox_send.Text;
            if (!string.IsNullOrEmpty(message)|| _ischeckRandom)
            {
                if (_messageChannel is not null)
                {
                    if (_ischeckRandom)
                    {
                        if (_RdbtnIsclick)
                        {
                            _messageChannel.Writer.TryWrite(rd.Next(22, 400).ToString());
                        }
                    }
                    else
                    {
                        _messageChannel.Writer.TryWrite(message);
                        //Console.WriteLine("Message added to channel: {0}", message);
                    }


                }
                else
                {
                    MessageBox.Show("请先连接");
                }


            }
        }

        private void CheckBox3_autoscroll_CheckedChanged(object sender, EventArgs e)
        {
            if (CheckBox3_autoscroll.Checked)
            {
                _autoScroll = true;
            }
            else
            {
                _autoScroll = false;
            }

        }

        //循环发送数据
        private bool _RdbtnIsclick = false;
        private CancellationTokenSource _ctsSendRd = new CancellationTokenSource();
        private void btn_random_Click(object sender, EventArgs e)
        {
            _ctsSendRd = new CancellationTokenSource();
            _RdbtnIsclick = !_RdbtnIsclick;

            if (_RdbtnIsclick)
            {
                btn_random.Text = "关闭循环发送";
                Task.Run(async () =>
                {
                    while (!_ctsSendRd.Token.IsCancellationRequested)
                    {
                        var time = TextBox_time.Text.ToInt();
                        await Task.Delay(time);
                        btn_send_Click(sender, e);
                    }

                }, _ctsSendRd.Token);
            }
            else
            {
                _ctsSendRd?.Cancel();
                btn_random.Text = "循环发送";
            }
        }

        //随机数
        private void CheckBox_random_CheckedChanged(object sender, EventArgs e)
        {
            _ischeckRandom = !_ischeckRandom;
        }

        private void CheckBox_savetofill_CheckedChanged(object sender, EventArgs e)
        {
            _log = !_log;
            if (_log)
            {
                timer1.Start();
            }
            else
            {
                timer1.Stop();
            }
        }

        //LogBox值改变后
        private void LogAppend()
        {
            // 确保文件操作在后台线程中进行，避免阻塞UI线程
            var logContent = LogBox.Text;
            try
            {
                using (StreamWriter writer = new StreamWriter(logFilePath))
                {
                    // 如果文件非空，则在内容前加上换行符
                    if (File.Exists(logFilePath) && new FileInfo(logFilePath).Length > 0)
                    {
                        writer.WriteLine();
                    }
                    // 写入当前LogBox的内容
                    writer.Write(logContent);
                }
            }
            catch (Exception)
            {

                throw;
            }
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            if (_log)
            {
                LogAppend();
            }
        }
    }
}
